package com.isyscore.os.permission.exception;

import com.isyscore.device.common.exception.BaseErrorCode;
import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 异常枚举
 * 0                - 成功
 * -1               - 没有被处理到的异常，一般很少会出现
 * 100 - 199        - 通用异常，如：参数不合法、未登陆、无权限等
 * 1000 - 1999      - 设备模型相关
 * 2000 - 2999      - 产品相关
 * 3000 - 3999      - 驱动、驱动实例相关
 * 4000 - 4999      - 网关相关
 * 5000 - 5999      - 设备相关
 * 6000 - 6999      - 节点模型
 * 7000 - 7999      - 规则引擎
 * 8000 - 8999      - 视频组态
 * 9000 - 9999      - 智能网关本地相关
 * 40000 - 41000    - 权限
 *
 * @author felixu
 * @since 2020.08.24
 */
@Getter
@AllArgsConstructor
public enum ErrorCode implements BaseErrorCode {

    /*-------------------------------- 成功 ------------------------------*/
    OK(0, "成功", ErrorGroup.GENERAL),

    /*-------------------------------- 失败(大多为没有被处理到的特殊异常) ------------------------------*/
    FAIL(-1, "出现未知错误，请稍后再试", ErrorGroup.GENERAL),
    FAIL_2(1, "操作失败，未知错误", ErrorGroup.GENERAL),
    MISSING_CODE(-2, "当前错误信息: {0}，缺失真正 code，请联系开发者处理", ErrorGroup.GENERAL),

    /*-------------------------------- 通用异常 ------------------------------*/
    PARAM_ERROR(100, "您提交的数据不符合要求", ErrorGroup.GENERAL),
    LOGIN_REQUIRED(101, "请(重新)登录", ErrorGroup.GENERAL),
    AUTHORIZATION_REQUIRED(102, "您没有执行该操作的权限", ErrorGroup.GENERAL),
    MISSING_SERVLET_REQUEST_PARAMETER(103, "不能为空", ErrorGroup.GENERAL),
    SYSTEM_DATA_CANNOT_OPERATE(104, "系统内置的数据无法被执行此操作", ErrorGroup.GENERAL),
    CANNOT_FOUND_BY_KEY(105, "无法通过该关键词查询到数据，请刷新重试", ErrorGroup.GENERAL),
    NAME_HAS_EXISTED(106, "当前使用的名称已经存在", ErrorGroup.GENERAL),
    IDENTIFIER_HAS_EXISTED(107, "当前使用的标识符已经存在", ErrorGroup.GENERAL),
    FILE_SHOULD_NOT_EMPTY(108, "文件不能为空", ErrorGroup.GENERAL),
    FILE_NOT_EXIST(109, "文件不存在", ErrorGroup.GENERAL),
    FILE_NAME_CAN_NOT_EMPTY(110, "文件名不能为空", ErrorGroup.GENERAL),
    FILE_NAME_VALIDATE_FAIL(111, "支持大小写英文字母、数字、下划线、中划线、点号、英文括号，不超过 64 个字符", ErrorGroup.GENERAL),
    SEND_MQ_TIMEOUT(112, "与中间件通讯超时，请稍后重试", ErrorGroup.GENERAL),
    REQUEST_TOO_FAST(113, "请求过快，请稍后再试", ErrorGroup.GENERAL),
    ID_NOT_NULL(114, "id不能为空", ErrorGroup.GENERAL),
    IP_ADDRSS_ILLEGAL(115, "ip地址不合法", ErrorGroup.GENERAL),
    NAME_MUST_LESS_32(116, "名称必须小于32个字符", ErrorGroup.GENERAL),
    PATH_PARAM_DATA_TYPE_ERROR(117, "路径参数数据类型出错", ErrorGroup.GENERAL),
    INPUT_PARAM_ILLEGAL(118, "入参非法,请检查输入参数或格式", ErrorGroup.GENERAL),
    LABEL_CANT_CONTAIN_JING(119, "{0}不能包括#号", ErrorGroup.GENERAL),
    PRODUCT_KEY_MUST_11(120, "设备类Key必须11位", ErrorGroup.GENERAL),
    SECRET_MUST_16(121, "设备密钥必须16位", ErrorGroup.GENERAL),
    DEVICE_ID_MUST_1_64(122, "设备id必须在1-64位", ErrorGroup.GENERAL),
    SQLLITE_CONNECTION_FAILURE(123, "无法初始化 sqlite 数据库连接", ErrorGroup.GENERAL),
    ENUM_PARAMS_ERROR(124, "枚举值不符合要求", ErrorGroup.GENERAL),
    RANGE_PARAM_SIZE_ERROR(125, "范围值参数个数不对", ErrorGroup.GENERAL),
    EXPORT_FILE_FAILURE(126, "写出文件失败", ErrorGroup.GENERAL),
    FILE_UPLOAD_FAILURE(127, "上传文件失败", ErrorGroup.GENERAL),
    FILE_DOWNLOAD_FAILURE(128, "下载文件失败", ErrorGroup.GENERAL),
    LOGIN_FAILED(129, "登录失败，请检查登录信息是否正确", ErrorGroup.GENERAL),
    ACCESS_INFO_EXIST(130, "登录信息已经被使用，请重新设置", ErrorGroup.GENERAL),
    NOT_EXIST_ANY_DATA(131, "不存在任何数据", ErrorGroup.GENERAL),
    IP_ADDRSS_NOT_NULL(132, "ip地址不能为空", ErrorGroup.GENERAL),
    USERPAGE_ERROR(133, "{0}", ErrorGroup.GENERAL),
    COMMON_ERROR(134, "{0}", ErrorGroup.GENERAL),
    VERSION_ILLEGAL(135, "版本格式不正确:{0}", ErrorGroup.GENERAL),
    SCRIPT_ERROR(136, "脚本错误：{0}", ErrorGroup.GENERAL),
    SCRIPT_RUN_ERROR(137, "脚本运行异常：{0}", ErrorGroup.GENERAL),
    SCRIPT_RETURN_TYPE_ERROR(138, "脚本返回值类型错误", ErrorGroup.GENERAL),
    SCRIPT_ENCODE_ERROR(139, "脚本编码转换错误", ErrorGroup.GENERAL),
    USER_NOT_EXIST(140, "用户不存在,请重新登录", ErrorGroup.GENERAL),
    OLD_PASSWORD_ERROR(141, "原密码错误", ErrorGroup.GENERAL),
    DEVICE_DATA_UP_RES_SCRIPT_ERROR(142, "设备上报数据回应时,脚本异常", ErrorGroup.GENERAL),
    NOT_NULL(143, "{0}不能为空", ErrorGroup.GENERAL),
    LICENSE_INFO_ERROR(144, "当前应用不可用，请联系更换License授权", ErrorGroup.GENERAL),
    ERROR_SIGN(145, "无效签名：{0}", ErrorGroup.GENERAL),
    TENANT_LICENSE_ERROR(146, "多租户授权异常，创建失败", ErrorGroup.GENERAL),
    TENANT_MANAGER_LICENSE_ERROR(147, "租户管理授权异常，创建失败", ErrorGroup.GENERAL),
    TENANT_LICENSE_EXCEED_LIMIT(148, "租户数量已超出授权限制，创建失败", ErrorGroup.GENERAL),
    APP_CODE_NOT_AUTHED(149, "应用未授权，跨服务调用失败：{0}", ErrorGroup.GENERAL),
    TENANT_NOT_AUTHED(150, "租户未授权，跨服务调用失败：{0}", ErrorGroup.GENERAL),

    /*-------------------------------- 权限 ------------------------------*/
    USER_DOES_NOT_EXIST(40000, "账号不存在，请重试", ErrorGroup.PERMISSION),
    ACCOUNT_OR_PASSWORD_ERROR(40002, "您输入的登录名或密码错误", ErrorGroup.PERMISSION),
    DATA_ROLE_EXISTS(40003, "数据角色名称已经存在", ErrorGroup.PERMISSION),
    DATA_ROLE_UPDATED_DOES_NOT_EXIST(40004, "待更新的数据角色不存在", ErrorGroup.PERMISSION),
    FUNCTION_ROLE_EXISTS(40005, "功能角色名称已经存在", ErrorGroup.PERMISSION),
    ROLE_HAS_PERSONNEL(40006, "无法删除该角色，请变更相关用户角色后再进行操作", ErrorGroup.PERMISSION),
    SUBSERVICE_PUBLISHING(40007, "子服务发布中，请稍后访问", ErrorGroup.PERMISSION),
    CHILD_SERVICE_COMMUNICATION_EXCEPTION(40008, "正在加载配置信息，请等待", ErrorGroup.PERMISSION),
    REGISTRY_ACCESS_CALLBACK_FAILED(40009, "注册中心获取权限回调结果失败", ErrorGroup.PERMISSION),
    REGISTRY_SERVICE_FAILED_GET_APPLICATION_INFORMATION(40010, "注册中心服务获取应用信息失败", ErrorGroup.PERMISSION),
    SUBSYSTEM_DATA_PERMISSION_CALLBACK_INTERFACE_FAILED(40011, "子系统数据权限回调接口获取失败", ErrorGroup.PERMISSION),
    ACL_CAN_NOT_NULL(40012, "权限不能为空", ErrorGroup.PERMISSION),
    ADD_TYPE_ERROR(40013, "添加组织类型异常", ErrorGroup.PERMISSION),
    UPDATE_TYPE_ERROR(40014, "修改组织类型异常", ErrorGroup.PERMISSION),
    DELETE_TYPE_ERROR(40015, "删除组织类型异常", ErrorGroup.PERMISSION),
    TYPE_HAS_CHILD(40016, "该类型下存在组织信息，不可删除", ErrorGroup.PERMISSION),
    HAS_NO_RENTAL_TYPE(40017, "组织类型不存在", ErrorGroup.PERMISSION),
    PRIVIDGE_INFO_INVALID(40018, "权限信息不合法", ErrorGroup.PERMISSION),
    HAS_NO_PARENT_ACL(40019, "父级菜单非法", ErrorGroup.PERMISSION),
    PARENT_ACL_NO_PRIVIDGE(40020, "功能权限不能创建子权限", ErrorGroup.PERMISSION),
    APPCODE_REQUIRED(40021, "appcode不能为空", ErrorGroup.PERMISSION),
    CODE_IS_REPEAT(40022, "权限标识重复", ErrorGroup.PERMISSION),
    NAME_IS_REPEAT(40023, "权限名称重复", ErrorGroup.PERMISSION),
    TYPE_NAME_EXISTS(40024, "组织类型名称已存在", ErrorGroup.PERMISSION),
    RENTAL_HAS_CHILDREN_RENTAL(40025, "该组织拥有下级组织", ErrorGroup.PERMISSION),
    RENTAL_HAS_RELATE_USER(40026, "组织有关联的用户，不可删除", ErrorGroup.PERMISSION),
    RENTAL_CODE_EXIST(40027, "组织代码已存在", ErrorGroup.PERMISSION),
    PARENT_RENTAL_NOT_EXIST(40028, "上级组织不存在", ErrorGroup.PERMISSION),
    PARENT_CANNOT_SELF(40029, "上级组织不能是自己", ErrorGroup.PERMISSION),
    PARENT_CANNOT_CHILD(40030, "上级组织不能是已有的下级", ErrorGroup.PERMISSION),
    RENTAL_NOT_EXIST(40031, "组织不存在", ErrorGroup.PERMISSION),
    USER_DISABLED(40032, "用户已被禁用，不可登录", ErrorGroup.PERMISSION),
    USER_EXT_KEY_MAX(40033, "用户自定义拓展信息key不超过{0}位", ErrorGroup.PERMISSION),
    USER_EXT_VAL_MAX(40034, "用户自定义拓展信息value不超过{0}位", ErrorGroup.PERMISSION),
    LOGIN_NAME_EXIST(40036, "登录名已存在", ErrorGroup.PERMISSION),
    TENANT_ID_EXIST(40037, "该租户ID已存在", ErrorGroup.PERMISSION),
    GET_USER_INFO_FAIL(40038, "获取用户信息失败", ErrorGroup.PERMISSION),
    ROLE_NOT_EXIST(40039, "角色不存在", ErrorGroup.PERMISSION),
    AUTH_ROLE_NOT_EXIST(40040, "数据角色不存在", ErrorGroup.PERMISSION),
    GET_ACL_FROM_APP_FAIL(40041, "从应用{0}获取权限失败", ErrorGroup.PERMISSION),
    HAS_CHILD_ACL(40042, "存在下级权限，不可操作", ErrorGroup.PERMISSION),
    ACL_USED_BY_ROLE(40043, "权限被角色使用，不可删除", ErrorGroup.PERMISSION),
    DATA_MODULE_NOT_EXIST(40044, "数据权限不存在", ErrorGroup.PERMISSION),
    DATA_MODULE_EXIST(40045, "该应用及namespace下数据权限已存在", ErrorGroup.PERMISSION),
    ACL_NOT_EXIST(40046, "功能权限不存在", ErrorGroup.PERMISSION),
    PARENT_ACL_CANNOT_SELF(40047, "上级权限不能是自己", ErrorGroup.PERMISSION),
    PARENT_ACL_CANNOT_CHILD(40048, "上级权限不能是已有的下级", ErrorGroup.PERMISSION),
    PARENT_ACL_NOT_EXIST(40049, "上级权限不存在", ErrorGroup.PERMISSION),
    REPEATLLY_LOGIN(10002, "该用户已在其它客户端登录，当前会话已失效", ErrorGroup.PERMISSION),
    TENANT_NOT_EXIST(10004, "没有查找到该租户的信息", ErrorGroup.PERMISSION),
    DEFAULT_TENANT_NOT_ALLOW_UPDATE(10006, "内置租户信息不允许变更", ErrorGroup.PERMISSION),
    LOGIN_NAME_FORMAT_ERROR(10008, "登录名需要满足 用户标识@租户ID 的格式,例如user@system", ErrorGroup.PERMISSION),
    LOGIN_NAME_TENANT_MISMATCH(10010, "登录名中的租户ID与实际租户ID不匹配", ErrorGroup.PERMISSION),
    TENANT_DISABLED(10012, "该用户所属的租户已被禁用", ErrorGroup.PERMISSION),
    DUBBO_CLIENT_NOT_INITIALIZE(10014, "DUBBO客户端无法初始化，请检查配置", ErrorGroup.PERMISSION),
    REG_CENTER_REQUEST_FAILED(10016, "从应用中心获取应用列表失败", ErrorGroup.PERMISSION),
    TENANT_ID_CONTAINS_RESERVED_WORD(10018, "租户ID不能为系统保留关键字", ErrorGroup.PERMISSION),
    TENANT_ID_ERROR(10019, "登录名的租户ID与当前租户不匹配", ErrorGroup.PERMISSION),
    DIOP_IMPORT_ERROR(10020, "数据导入失败", ErrorGroup.PERMISSION),
    DIOP_NO_SUPER_ADMIN_IMPORT_TENANT(10021, "该用户不是超级管理员，不能导入租户信息", ErrorGroup.PERMISSION),
    DIOP_NO_SUPER_ADMIN_EXPORT_TENANT(10022, "该用户不是超级管理员，不能导出租户信息", ErrorGroup.PERMISSION),
    DIOP_IMPORT_PATH_NO_TENANT_INFO(10023, "导入路径中未找到租户信息，导入失败", ErrorGroup.PERMISSION),
    IMPORT_MAIN_DATA_REPEAT(10024, "导入{0}数据重复，{1}", ErrorGroup.GENERAL),
    IMPORT_REF_DATA_NOT_EXIST(10025, "导入{0}数据关联不存在，{1}", ErrorGroup.GENERAL),
    IMPORT_DATA_ERROR(10026, "导入{0}数据有误，{1}", ErrorGroup.GENERAL),
    APPCODE_NOT_FOUND(10027, "应用代码未找到:{0}", ErrorGroup.GENERAL),
    ACL_ID_NOT_FOUND(10028, "权限ID未找到:{0}", ErrorGroup.GENERAL),
    ROLE_ID_NOT_FOUND(10029, "角色ID未找到:{0}", ErrorGroup.GENERAL),
    PARAM_FORMAT_ERROR(10030, "参数{0}格式有误:{1}", ErrorGroup.GENERAL),
    REG_APP_NOT_FOUND(10031, "未找到该应用的注册信息：{0}", ErrorGroup.MESSAGE_CENTER),
    APP_ID_NOT_FOUND(10032, "应用ID未找到：{0}", ErrorGroup.GENERAL),
    APPCODE_OR_SECRET_ERROR(10033, "应用编码或应用密钥有误", ErrorGroup.GENERAL),
    TTL_CAN_NOT_BE_EMPTY(10034, "TTL不能为空", ErrorGroup.GENERAL),
    IMPORT_INITIALLY_DATA_REPEAT(10035, "权限标识与全局功能权限点重复，无权限更新", ErrorGroup.GENERAL),

    /*-------------------------------- 消息中心 ------------------------------*/
    SYSTEM_MESSAGE_CAN_NOT_EDIT(41000, "系统内置消息主题不能修改", ErrorGroup.MESSAGE_CENTER),
    SYSTEM_MESSAGE_CAN_NOT_DELETE(41001, "系统内置消息主题不能删除", ErrorGroup.MESSAGE_CENTER),
    //    OTHER_PEOPLE_MESSAGE_CAN_NOT_UPDATE(41002, "别人的消息主题不能修改", ErrorGroup.MESSAGE_CENTER),
    MESSAGE_TOPIC_NOT_EXIST(41003, "消息主题不存在", ErrorGroup.MESSAGE_CENTER),
    MESSAGE_TOPIC_TOPIC_DUPLICATE(41004, "主题topic已存在", ErrorGroup.MESSAGE_CENTER),
    MESSAGE_TOPIC_NAME_DUPLICATE(41005, "主题名称已存在", ErrorGroup.MESSAGE_CENTER),
    CURRENT_USER_NOT_SUBSCRIBE_THIS_TOPIC(41006, "当前用户未订阅该消息主题", ErrorGroup.MESSAGE_CENTER),
    CURRENT_USER_SUBSCRIBE_THIS_TOPIC(41007, "当前用户已订阅该消息主题", ErrorGroup.MESSAGE_CENTER),
    /*-------------------------------- 结束 ------------------------------*/;


    /**
     * 返回的 code，非 0 表示错误
     */
    private int code;

    /**
     * 发生错误时的描述
     */
    private String message;

    /**
     * 错误码分组
     */
    private final ErrorGroup group;

    /**
     * 由于经过很长时间的迭代，才出现要统一返回，统一异常 code
     * 故而兼容原 BusinessException 和 SystemException 解析到 ErrorCode
     * 避免大规模改代码
     * 后续可能会逐步移除
     */
    public static ErrorCode parse(String message) {
        for (ErrorCode errorCode : ErrorCode.values()) {
            if (errorCode.message.equals(message)) {
                return errorCode;
            }
        }
        return MISSING_CODE;
    }

    /**
     * 根据shadow上报的设备控制响应code获取对应的ErrorCode
     * 如果是设备返回的code,可能找不到
     */
    public static ErrorCode parse(int code) {
        for (ErrorCode errorCode : ErrorCode.values()) {
            if (errorCode.code == code) {
                return errorCode;
            }
        }
        return MISSING_CODE;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    /**
     * 根据ErrorCode的值搜索对应的枚举对象
     */
    public static ErrorCode getErrorCodeByCodeVal(Integer code) {
        if (code == null) {
            return null;
        }
        ErrorCode[] codes = ErrorCode.values();
        for (ErrorCode errorCode : codes) {
            if (errorCode.getCode() == code) {
                return errorCode;
            }
        }
        return null;
    }
}
